package com.yongqi.config;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.yongqi.shiro.BackShiroRealm;
import com.yongqi.shiro.DefaultModularRealm;
import com.yongqi.shiro.MyShiroRealm;
import com.yongqi.task.ScheduleTask;

/**
 * Shiro 配置
 *
 * Apache Shiro 核心通过 Filter 来实现，就好像SpringMvc 通过DispachServlet 来主控制一样。 既然是使用
 * Filter 一般也就能猜到，是通过URL规则来进行过滤和权限校验，所以我们需要定义一系列关于URL的规则和访问权限。
 *
 */
@Configuration
public class ShiroConfiguration {
	/**
	 * 拦截器
	 * 
	 * @param securityManager
	 * @return shiroFilterFactoryBean
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
		System.out.println("shiroFilter");
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager((org.apache.shiro.mgt.SecurityManager) securityManager);
		// 拦截器.
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 配置不会被拦截的链接 顺序判断
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/assets/**", "anon");
		filterChainDefinitionMap.put("/logo/**", "anon");
		filterChainDefinitionMap.put("/fonts/**", "anon");
		filterChainDefinitionMap.put("/css/fonts/**", "anon");
		// 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
		// 过滤链定义，从上向下顺序执行，一般将/**放在最为下边:这是一个坑呢，一不小心代码就不好使了;
		// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
		filterChainDefinitionMap.put("/welcome", "anon");	//管理后台登录
		filterChainDefinitionMap.put("/welcome/news", "anon");
		filterChainDefinitionMap.put("/back/login", "anon");	//管理后台登录
		filterChainDefinitionMap.put("/back/loginValidate", "anon");	//管理后台登录验证
		filterChainDefinitionMap.put("/login", "anon");	//管理后台登录
		filterChainDefinitionMap.put("/loginValidate", "anon");	//管理后台登录验证
		filterChainDefinitionMap.put("/login/regFamily", "anon");// 进入controller
		filterChainDefinitionMap.put("/getVerify", "anon");// 显示验证码
		filterChainDefinitionMap.put("/validateCode", "anon");
		// filterChainDefinitionMap.put("/menu/**", "anon");
		filterChainDefinitionMap.put("/family/checkfamilyaccount", "anon");// 校验家庭账户是否已存在
		filterChainDefinitionMap.put("/family/register", "anon");// 提交家庭账户
		filterChainDefinitionMap.put("/family/forgetPassword", "anon");// 提交家庭账户/gradesign
		filterChainDefinitionMap.put("/family/sendEmailValidation", "anon");
		filterChainDefinitionMap.put("/family/getValidationCode", "anon");
		filterChainDefinitionMap.put("/family/changePwd", "anon");
		filterChainDefinitionMap.put("/wx/**", "anon");
//		filterChainDefinitionMap.put("/wx/bill", "anon");
//		filterChainDefinitionMap.put("/wx/member", "anon");
		
		filterChainDefinitionMap.put("/**", "authc");
		// filterChainDefinitionMap.put("/login", "authc");
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
		// 仍然是通過controller請求响应
		shiroFilterFactoryBean.setLoginUrl("/login");
		// 登录成功后要跳转的链接
		//shiroFilterFactoryBean.setSuccessUrl("/index");

		// 未授权界面;
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	/**
	 * 凭证匹配器，此处使用md5算法，散列两次 已经将密码校验交给了MyShiroRealam中SimpleAuthenticationInfo
	 * 
	 * @return hashedCredentialsMatcher
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法
		hashedCredentialsMatcher.setHashIterations(2);// 散列次数md5(md5(""))
		return hashedCredentialsMatcher;
	}
	@Bean
	public EhCacheManager ehCacheManager() {
		System.out.println("ShiroConfiguration.ehCacheManager");
		EhCacheManager cacheManager = new EhCacheManager();
		cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
		return cacheManager;
	}
	/**
	 * 前台管理域 账号密码验证；授权
	 * 
	 * @return myShiroRealm
	 */
	@Bean
	public MyShiroRealm myShiroRealm() {
		MyShiroRealm myShiroRealm = new MyShiroRealm();
		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myShiroRealm;
	}
	/**
	 * 后台管理域 账号密码验证；授权
	 * 
	 * @return myShiroRealm
	 */
	@Bean
	public BackShiroRealm backShiroRealm() {
	    BackShiroRealm backShiroRealm = new BackShiroRealm();
	    backShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
	return backShiroRealm;
	}
	/**
	 * 定时任务
	 * No SecurityManager accessible to the calling code, either bound to the org.a
	 */
	@Bean
	public ScheduleTask scheduleTask() {
	    ScheduleTask scheduleTask = new ScheduleTask();
	    return scheduleTask;
	}
	/**
	 * 项目自定义authenticator
	 */
	@Bean
	public DefaultModularRealm defaultModularRealm() {
	    DefaultModularRealm defaultModularRealm = new DefaultModularRealm();
	    Map<String, Object> map = new HashMap<String, Object>();
	    map.put("backShiroRealm", backShiroRealm());
	    map.put("myShiroRealm", myShiroRealm());
	    defaultModularRealm.setDefinedRealms(map);
	    return defaultModularRealm;
	}
	/**
	 * 安全管理器 所有配置的入口；所有与安全相关的操作都会与SecurityManager交互，且管理着所有的Subject
	 * 实现验证，授权，Session管理操作的接口
	 * 
	 * @return securityManager
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setAuthenticator(defaultModularRealm());
		securityManager.setRealm(backShiroRealm());
		securityManager.setRealm(myShiroRealm());
		
//		securityManager.setCacheManager(ehCacheManager());
		//SecurityManager加载到内存中
		SecurityUtils.setSecurityManager(securityManager);  
		return securityManager;
	}
        //将SecurityManager设置到系统运行环境  
	  
       
	/**
	 * 开启shiro aop注解支持，使用代理方式；所以需要开启代码支持？？？？
	 * 
	 * @param securityManager
	 * @return authorizationAttributeSourceAdvisor
	 */
	// @Bean
	// public AuthorizationAttributeSourceAdvisor
	// authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
	// AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new
	// AuthorizationAttributeSourceAdvisor();
	// authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
	// return authorizationAttributeSourceAdvisor;
	// }
//	@Bean
//    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
//        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
//        creator.setProxyTargetClass(true);
//        return creator;
//    }
}